package com.lemon.exam.common.redis.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * Redis List 操作 类对象
 *
 * @author Lemon
 * @since 2025/7/4 18:07
 */
public final class ListOperations extends BaseOperations {
    public ListOperations(ObjectMapper objectMapper, ReactiveRedisTemplate<String, Object> template) {
        super(objectMapper, template);
    }

    /**
     * 左侧添加元素
     *
     * @param key   键
     * @param value 值
     * @return 是否成功
     */
    public Mono<Boolean> leftPush(String key, Object value) {
        return withRetry(
                template.opsForList().leftPush(key, value).map(v -> v != null && v == 1),
                "redis list leftPush key: %s".formatted(key)
        ).onErrorResume(err -> Mono.just(false));
    }

    /**
     * 右侧添加元素
     *
     * @param key   键
     * @param value 值
     * @return 是否成功
     */
    public Mono<Boolean> rightPush(String key, Object value) {
        return withRetry(
                template.opsForList().rightPush(key, value).map(v -> v != null && v == 1),
                "redis list rightPush key: %s".formatted(key)
        ).onErrorResume(err -> Mono.just(false));
    }

    /**
     * 获取指定区间的元素
     *
     * @param key   键
     * @param start 开始位置
     * @param end   结束位置
     * @param clazz 泛型
     * @return 元素列表
     */
    public <T> Flux<T> range(String key, long start, long end, Class<T> clazz) {
        return withRetry(
                template.opsForList().range(key, start, end).mapNotNull(toGeneric(clazz)),
                "redis list range key: %s".formatted(key)
        ).onErrorResume(err -> Flux.empty());
    }

    /**
     * 删除指定元素
     *
     * @param key   键
     * @param count 删除数量
     * @param value 值
     * @return 是否成功
     */
    public Mono<Boolean> del(String key, long count, Object value) {
        return withRetry(
                template.opsForList().remove(key, count, value).map(v -> v != null && v == count),
                "redis list del key: %s".formatted(key)
        ).onErrorResume(err -> Mono.just(false));
    }
}
